/*
 * @Author: 0x9DEFA478
 * @Date: 2022-01-23 15:31:56
 * @LastEditTime: 2022-02-24 19:22:20
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "./H_NES_Console.h"




static void ArrayCopy(void* dst,void* src,int Size){
  while(Size>0){
    Size--;
    ((Hbyte*)dst)[Size]=((Hbyte*)src)[Size];
  }
}




//预退出调用
void H_NES_Console_PreExit(H_NES_Console* Console){
  H_NES_Message msg;

  Console->LL_Function.ExitCallback(Console->LL_Function.v);

  msg.FunctionIndex=vH_NES_Message_FunctionIndex_Stop;
  msg.v=NULL;
  Console->LL_Function.Thread.MessageSned(Console->MessageQueue.Ack,&msg);
}

#define cToByteArray(_in_v) ((Hbyte*)&_in_v)
#define oCopyToArray(_in_dst,_in_v,_in_Size) ArrayCopy(&_in_dst,cToByteArray(_in_v),_in_Size)
#define oCopyToValue(_in_src,_in_v,_in_Size) ArrayCopy(cToByteArray(_in_v),&_in_src,_in_Size)

void H_NES_Console_GetProgress(H_NES_Console* Console,void* Progress){
  Hbyte* p;

  p=Progress;



  //CPU
  oCopyToArray(p[0],Console->CPU.MCLK,4);

  p[4]=Console->CPU.Register.A;
  p[5]=Console->CPU.Register.X;
  p[6]=Console->CPU.Register.Y;
  p[7]=Console->CPU.Register.P;
  p[8]=Console->CPU.Register.S;

  oCopyToArray(p[9],Console->CPU.Register.PC,2);

  p[11]=cToByteArray(Console->CPU.APU_Clock)[0];

  oCopyToArray(p[12],Console->CPU.Status,2);
  
  oCopyToArray(p[14],Console->CPU.DMA.OAMADDR,2);

  //APU
  oCopyToArray(p[16],Console->CPU.APU.FrameCounter.Reg_4017_CPUClock,4);
  //Pulse1
  oCopyToArray(p[20],Console->CPU.APU.Channel.Pulse1.Timer.Period_Cnt,4);

  oCopyToArray(p[24],Console->CPU.APU.Channel.Pulse1.Sweep.TargetTimerPeriod,2);

  oCopyToArray(p[26],Console->CPU.APU.Channel.Pulse1.Sweep.Reg_4001_PCnt,2);
  
  p[28]=Console->CPU.APU.Channel.Pulse1.Envelope.DividerValue;
  p[29]=Console->CPU.APU.Channel.Pulse1.Envelope.StartFlag;
  p[30]=Console->CPU.APU.Channel.Pulse1.Envelope.DecayLevel;

  p[31]=Console->CPU.APU.Channel.Pulse1.Sequencer.Step;

  oCopyToArray(p[32],Console->CPU.APU.Channel.Pulse1.LengthCounter.Period_Cnt,2);
  //Pulse2
  oCopyToArray(p[34],Console->CPU.APU.Channel.Pulse2.Timer.Period_Cnt,4);

  oCopyToArray(p[38],Console->CPU.APU.Channel.Pulse2.Sweep.TargetTimerPeriod,2);

  oCopyToArray(p[40],Console->CPU.APU.Channel.Pulse2.Sweep.Reg_4005_PCnt,2);
  
  p[42]=Console->CPU.APU.Channel.Pulse2.Envelope.DividerValue;
  p[43]=Console->CPU.APU.Channel.Pulse2.Envelope.StartFlag;
  p[44]=Console->CPU.APU.Channel.Pulse2.Envelope.DecayLevel;

  p[45]=Console->CPU.APU.Channel.Pulse2.Sequencer.Step;

  oCopyToArray(p[46],Console->CPU.APU.Channel.Pulse2.LengthCounter.Period_Cnt,2);
  //Triangle
  oCopyToArray(p[48],Console->CPU.APU.Channel.Triangle.Timer.Period_Cnt,4);

  oCopyToArray(p[52],Console->CPU.APU.Channel.Triangle.LinerCounter.Reg_4008_Cnt,2);

  oCopyToArray(p[54],Console->CPU.APU.Channel.Triangle.LengthCounter.Period_Cnt,2);

  p[56]=Console->CPU.APU.Channel.Triangle.Output;
  //Noise
  oCopyToArray(p[57],Console->CPU.APU.Channel.Noise.Timer.Period_Cnt,4);

  p[61]=Console->CPU.APU.Channel.Noise.Reg_400C;
  p[62]=Console->CPU.APU.Channel.Noise.ModeFlag;

  p[63]=Console->CPU.APU.Channel.Noise.Envelope.DividerValue;
  p[64]=Console->CPU.APU.Channel.Noise.Envelope.StartFlag;
  p[65]=Console->CPU.APU.Channel.Noise.Envelope.DecayLevel;

  oCopyToArray(p[66],Console->CPU.APU.Channel.Noise.ShiftRegister,2);

  oCopyToArray(p[68],Console->CPU.APU.Channel.Noise.LengthCounter.Period_Cnt,2);
  //DMC
  oCopyToArray(p[70],Console->CPU.APU.Channel.DMC.Timer.Period_Cnt,4);

  p[74]=Console->CPU.APU.Channel.DMC.Reg_4010;
  
  oCopyToArray(p[75],Console->CPU.APU.Channel.DMC.Reader.Address,2);
  oCopyToArray(p[77],Console->CPU.APU.Channel.DMC.Reader.NumOfLastByte,2);
  oCopyToArray(p[79],Console->CPU.APU.Channel.DMC.Reader.Period_Address,2);
  oCopyToArray(p[81],Console->CPU.APU.Channel.DMC.Reader.Period_NumOfLastByte,2);

  p[83]=Console->CPU.APU.Channel.DMC.Shifter.NumOfLastBit;
  p[84]=Console->CPU.APU.Channel.DMC.Shifter.Value;

  p[85]=Console->CPU.APU.Channel.DMC.MultFlag;
  p[86]=Console->CPU.APU.Channel.DMC.OutputLevel;

  p[87]=Console->CPU.APU.Status.Reg_4015_W;

  //PPU
  p[88]=(Hbyte)(((Husize)(Console->PPU.NameTable[0]-(Hbyte*)Console->PPU.VRAM))/1024U);
  p[89]=(Hbyte)(((Husize)(Console->PPU.NameTable[1]-(Hbyte*)Console->PPU.VRAM))/1024U);
  p[90]=(Hbyte)(((Husize)(Console->PPU.NameTable[2]-(Hbyte*)Console->PPU.VRAM))/1024U);
  p[91]=(Hbyte)(((Husize)(Console->PPU.NameTable[3]-(Hbyte*)Console->PPU.VRAM))/1024U);
  
  p[92]=Console->PPU.Register.Register[0];
  p[93]=Console->PPU.Register.Register[1];
  p[94]=Console->PPU.Register.Register[2];
  p[95]=Console->PPU.Register.Register[3];
  oCopyToArray(p[96],Console->PPU.Register.Internal.v,2);
  oCopyToArray(p[98],Console->PPU.Register.Internal.t,2);
  p[100]=Console->PPU.Register.Internal.x;
  p[101]=Console->PPU.Register.Internal.w;
  if(Console->PPU.Register.Internal.IsAddXY==0){
    p[102]=0x00U;
  }else{
    p[102]=0xFFU;
  }
  p[103]=Console->PPU.Register.PPUDATA.ReadBuffer;

  oCopyToArray(p[104],Console->PPU.Palettes[0],32);
  oCopyToArray(p[136],Console->PPU.OAM[0],256);

  p[392]=Console->PPU.VRAM_ScreenType;

  p[393]=Console->StandardController.Reg_4016_W;


}

void H_NES_Console_LoadProgress(H_NES_Console* Console,void* Progress){
  Hbyte* p;

  p=Progress;



  //CPU
  oCopyToValue(p[0],Console->CPU.MCLK,4);

  Console->CPU.Register.A=p[4];
  Console->CPU.Register.X=p[5];
  Console->CPU.Register.Y=p[6];
  Console->CPU.Register.P=p[7];
  Console->CPU.Register.S=p[8];

  oCopyToValue(p[9],Console->CPU.Register.PC,2);

  cToByteArray(Console->CPU.APU_Clock)[0]=p[11];

  oCopyToValue(p[12],Console->CPU.Status,2);
  
  oCopyToValue(p[14],Console->CPU.DMA.OAMADDR,2);

  //APU
  oCopyToValue(p[16],Console->CPU.APU.FrameCounter.Reg_4017_CPUClock,4);
  //Pulse1
  oCopyToValue(p[20],Console->CPU.APU.Channel.Pulse1.Timer.Period_Cnt,4);

  oCopyToValue(p[24],Console->CPU.APU.Channel.Pulse1.Sweep.TargetTimerPeriod,2);

  oCopyToValue(p[26],Console->CPU.APU.Channel.Pulse1.Sweep.Reg_4001_PCnt,2);
  
  Console->CPU.APU.Channel.Pulse1.Envelope.DividerValue=p[28];
  Console->CPU.APU.Channel.Pulse1.Envelope.StartFlag=p[29];
  Console->CPU.APU.Channel.Pulse1.Envelope.DecayLevel=p[30];

  Console->CPU.APU.Channel.Pulse1.Sequencer.Step=p[31];

  oCopyToValue(p[32],Console->CPU.APU.Channel.Pulse1.LengthCounter.Period_Cnt,2);
  //Pulse2
  oCopyToValue(p[34],Console->CPU.APU.Channel.Pulse2.Timer.Period_Cnt,4);

  oCopyToValue(p[38],Console->CPU.APU.Channel.Pulse2.Sweep.TargetTimerPeriod,2);

  oCopyToValue(p[40],Console->CPU.APU.Channel.Pulse2.Sweep.Reg_4005_PCnt,2);
  
  Console->CPU.APU.Channel.Pulse2.Envelope.DividerValue=p[42];
  Console->CPU.APU.Channel.Pulse2.Envelope.StartFlag=p[43];
  Console->CPU.APU.Channel.Pulse2.Envelope.DecayLevel=p[44];

  Console->CPU.APU.Channel.Pulse2.Sequencer.Step=p[45];

  oCopyToValue(p[46],Console->CPU.APU.Channel.Pulse2.LengthCounter.Period_Cnt,2);
  //Triangle
  oCopyToValue(p[48],Console->CPU.APU.Channel.Triangle.Timer.Period_Cnt,4);

  oCopyToValue(p[52],Console->CPU.APU.Channel.Triangle.LinerCounter.Reg_4008_Cnt,2);

  oCopyToValue(p[54],Console->CPU.APU.Channel.Triangle.LengthCounter.Period_Cnt,2);

  Console->CPU.APU.Channel.Triangle.Output=p[56];
  //Noise
  oCopyToValue(p[57],Console->CPU.APU.Channel.Noise.Timer.Period_Cnt,4);

  Console->CPU.APU.Channel.Noise.Reg_400C=p[61];
  Console->CPU.APU.Channel.Noise.ModeFlag=p[62];

  Console->CPU.APU.Channel.Noise.Envelope.DividerValue=p[63];
  Console->CPU.APU.Channel.Noise.Envelope.StartFlag=p[64];
  Console->CPU.APU.Channel.Noise.Envelope.DecayLevel=p[65];

  oCopyToValue(p[66],Console->CPU.APU.Channel.Noise.ShiftRegister,2);

  oCopyToValue(p[68],Console->CPU.APU.Channel.Noise.LengthCounter.Period_Cnt,2);
  //DMC
  oCopyToValue(p[70],Console->CPU.APU.Channel.DMC.Timer.Period_Cnt,4);

  Console->CPU.APU.Channel.DMC.Reg_4010=p[74];
  
  oCopyToValue(p[75],Console->CPU.APU.Channel.DMC.Reader.Address,2);
  oCopyToValue(p[77],Console->CPU.APU.Channel.DMC.Reader.NumOfLastByte,2);
  oCopyToValue(p[79],Console->CPU.APU.Channel.DMC.Reader.Period_Address,2);
  oCopyToValue(p[81],Console->CPU.APU.Channel.DMC.Reader.Period_NumOfLastByte,2);

  Console->CPU.APU.Channel.DMC.Shifter.NumOfLastBit=p[83];
  Console->CPU.APU.Channel.DMC.Shifter.Value=p[84];

  Console->CPU.APU.Channel.DMC.MultFlag=p[85];
  Console->CPU.APU.Channel.DMC.OutputLevel=p[86];

  Console->CPU.APU.Status.Reg_4015_W=p[87];

  //PPU
  Console->PPU.NameTable[0]=&((Hbyte*)Console->PPU.VRAM)[(Huint32)p[88]*1024U];
  Console->PPU.NameTable[1]=&((Hbyte*)Console->PPU.VRAM)[(Huint32)p[89]*1024U];
  Console->PPU.NameTable[2]=&((Hbyte*)Console->PPU.VRAM)[(Huint32)p[90]*1024U];
  Console->PPU.NameTable[3]=&((Hbyte*)Console->PPU.VRAM)[(Huint32)p[91]*1024U];
  
  Console->PPU.Register.Register[0]=p[92];
  Console->PPU.Register.Register[1]=p[93];
  Console->PPU.Register.Register[2]=p[94];
  Console->PPU.Register.Register[3]=p[95];
  oCopyToValue(p[96],Console->PPU.Register.Internal.v,2);
  oCopyToValue(p[98],Console->PPU.Register.Internal.t,2);
  Console->PPU.Register.Internal.x=p[100];
  Console->PPU.Register.Internal.w=p[101];
  if(p[102]==0x00U){
    Console->PPU.Register.Internal.IsAddXY=0;
  }else{
    Console->PPU.Register.Internal.IsAddXY=-1;
  }
  Console->PPU.Register.PPUDATA.ReadBuffer=p[103];

  oCopyToValue(p[104],Console->PPU.Palettes[0],32);
  oCopyToValue(p[136],Console->PPU.OAM[0],256);

  p[392]=Console->PPU.VRAM_ScreenType;

  p[393]=Console->StandardController.Reg_4016_W;


}

#undef cToByteArray



